home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
mus
/
misc
/
play_handler_s.lzh
/
play-handler
/
play-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-26
|
15KB
|
557 lines
/* playhandler: sowas wie /dev/audio fuer sparks
Mountlist:
Handler = L:PlayHandler
Priority = 5
Stacksize = 1000
GlobVec = -1
*/
#ifdef LATTICE
#define __USE_SYSBASE
#endif
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <devices/audio.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFLEN 512
#define BUFFERS 20
#define SAMPLES 8192
#define MIN(A,B) (((A)<(B))?(A):(B))
struct VHDR {
ULONG oneShotHiSamples,repeatHiSamples,samplesPerHiCycle;
UWORD samplesPerSec;
UBYTE ctOctave,sCompression;
LONG volume;
};
enum parserstates {init,vhdr,readover,body,no8svx,identifyhunk};
struct streaminfo {
UBYTE *buf[2];
ULONG buflen;
struct IOAudio req[5];
char which;
char deflt;
char played[2];
ULONG cnt;
UWORD samples;
char channel;
UBYTE parsebuf[sizeof(struct VHDR)];
UBYTE bufcnt;
ULONG chunkcnt;
enum parserstates parserstate;
};
struct DosPacket *getpacket(struct MsgPort *);
void replypacket(struct DosPacket *,LONG,LONG);
LONG playhandler(void);
void playpacket(struct streaminfo *,APTR,LONG);
void parsepacket(struct DosPacket *);
int openstream(struct DosPacket *);
#ifdef LATTICE
void geta4(void);
#endif
char *BSTR2C(char *);
void parsename(struct streaminfo *,LONG);
extern struct ExecBase *
#ifdef LATTICE
__far
#endif
AbsExecBase;
struct ExecBase *SysBase;
struct GfxBase *GfxBase;
struct DosLibrary *DOSBase;
LONG dmaclock;
LONG buffers;
static char version[]="$VER: PLAY-Handler V1.00 by JD - "
#ifdef SHARE
"Shareware Version"
#else
"Full Version licenced to "
"Joerg Dorchain"
#endif
;
/* saveds ??*/
LONG playhandler()
{
struct MsgPort *pp;
struct DosPacket *dp;
struct Process *me;
struct streaminfo *sip;
struct DeviceNode *dn,**pdn,*dn2;
struct DosInfo *di;
int die;
int open;
#ifdef LATTICE
geta4();
#endif
SysBase=AbsExecBase;
me=(struct Process *)SysBase->ThisTask;
if (me->pr_CLI!=NULL)
return 5;
pp=&me->pr_MsgPort;
WaitPort(pp);
dp=getpacket(pp);
dn=((struct DeviceNode *)BADDR(dp->dp_Arg3));
dn->dn_Task=pp;
replypacket(dp,DOSTRUE,0);
die=0;
open=0;
buffers=BUFFERS;
dmaclock=3579545;
if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))!=NULL)
{
if ((GfxBase->DisplayFlags&PAL)==NULL)
dmaclock=357945;
CloseLibrary((struct Library *)GfxBase);
}
for(;;)
{
WaitPort(pp);
if ((dp=getpacket(pp))!=NULL)
{
switch(dp->dp_Type)
{
case ACTION_FINDUPDATE:
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
if ((die==1)
#ifdef SHARE
||(open==1)
#endif
)
replypacket(dp,DOSFALSE,ERROR_OBJECT_IN_USE);
else
if(openstream(dp)==1)
{
open++;
#ifdef SHARE
die=1;
#endif
}
break;
case ACTION_END:
sip=(struct streaminfo *)dp->dp_Arg1;
if (sip->cnt!=0)
{
sip->req[sip->which].ioa_Request.io_Command=
sip->req[sip->which+2].ioa_Request.io_Command=CMD_WRITE;
sip->req[sip->which].ioa_Request.io_Flags=
sip->req[sip->which+2].ioa_Request.io_Flags=ADIOF_PERVOL;
sip->req[sip->which].ioa_Data=
sip->req[sip->which+2].ioa_Data=sip->buf[sip->which];
sip->req[sip->which].ioa_Length=
sip->req[sip->which+2].ioa_Length=sip->cnt;
sip->req[sip->which].ioa_Period=
sip->req[sip->which+2].ioa_Period=dmaclock/sip->samples;
sip->req[sip->which].ioa_Volume=
sip->req[sip->which+2].ioa_Volume=64;
sip->req[sip->which].ioa_Cycles=
sip->req[sip->which+2].ioa_Cycles=1;
if ((sip->channel==1)&&((sip->played[0]|sip->played[1])==0))
{
sip->req[4].ioa_Request.io_Command=CMD_STOP;
DoIO((struct IORequest *)&sip->req[4]);
}
BeginIO((struct IORequest *)&sip->req[sip->which]);
if (sip->channel==1)
{
BeginIO((struct IORequest *)&sip->req[sip->which+2]);
if ((sip->played[0]|sip->played[1])==0)
{
sip->req[4].ioa_Request.io_Command=CMD_START;
DoIO((struct IORequest *)&sip->req[4]);
}
}
WaitIO((struct IORequest *)&sip->req[sip->which]);
if (sip->channel==1)
WaitIO((struct IORequest *)&sip->req[sip->which+2]);
}
sip->req[4].ioa_Request.io_Command=CMD_RESET;
DoIO((struct IORequest *)&sip->req[4]);
CloseDevice((struct IORequest *)&sip->req[4]);
DeletePort(sip->req[0].ioa_Request.io_Message.mn_ReplyPort);
FreeMem(sip->buf[1],sip->buflen);
FreeMem(sip->buf[0],sip->buflen);
FreeMem(sip,sizeof(struct streaminfo));
open--;
replypacket(dp,DOSTRUE,0);
break;
case ACTION_READ:
case ACTION_SEEK:
case ACTION_SET_FILE_SIZE:
replypacket(dp,-1,ERROR_ACTION_NOT_KNOWN);
break;
case ACTION_WRITE:
parsepacket(dp);
replypacket(dp,dp->dp_Arg3,0);
break;
case ACTION_IS_FILESYSTEM:
replypacket(dp,0,0);
break;
case ACTION_DIE:
die=1;
replypacket(dp,DOSTRUE,0);
break;
case ACTION_MORE_CACHE:
buffers+=dp->dp_Arg1;
if(buffers<1)
buffers=1;
replypacket(dp,buffers,buffers);
break;
default:
replypacket(dp,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
break;
}
}
if ((open==0)&&(die==1))
{
if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",0))!=NULL)
{
if (DOSBase->dl_lib.lib_Version>36)
LockDosList(LDF_WRITE|LDF_ALL|LDF_DELETE);
di=BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
pdn=(struct DeviceNode **)&di->di_DevInfo;
Forbid();
while((dn2=BADDR(*pdn))!=dn)
pdn=(struct DeviceNode **)&dn2->dn_Next;
*pdn=(struct DeviceNode *)dn->dn_Next;
UnLoadSeg(dn->dn_SegList);
FreeMem(BADDR(dn->dn_Name),((UBYTE *)BADDR(dn->dn_Name))[0]+1);
FreeMem(BADDR(dn->dn_Handler),((UBYTE *)BADDR(dn->dn_Handler))[0]+1);
FreeMem(dn,sizeof(struct DeviceNode));
if (DOSBase->dl_lib.lib_Version>36)
UnLockDosList(LDF_WRITE|LDF_ALL|LDF_DELETE);
while((dp=getpacket(pp))!=NULL)
replypacket(dp,-1,ERROR_DEVICE_NOT_MOUNTED);
return 0;
}
die=0;
}
}
}
struct DosPacket *getpacket(mp)
struct MsgPort *mp;
{
struct Message *mn;
if ((mn=GetMsg(mp))==NULL)
return NULL;
return (struct DosPacket *)mn->mn_Node.ln_Name;
}
void replypacket(dp,arg1,arg2)
struct DosPacket *dp;
LONG arg1,arg2;
{
struct MsgPort *mp;
struct Message *mn;
mp=dp->dp_Port;
mn=dp->dp_Link;
mn->mn_Node.ln_Name=(char *)dp;
dp->dp_Port=&((struct Process *)SysBase->ThisTask)->pr_MsgPort;
dp->dp_Res1=arg1;
dp->dp_Res2=arg2;
PutMsg(mp,mn);
}
void playpacket(sip,buf,len)
struct streaminfo *sip;
APTR buf;
LONG len;
{
LONG cnt2;
cnt2=0;
while(sip->buflen-sip->cnt<=len-cnt2)
{
CopyMem(((UBYTE *)buf)+cnt2,
((UBYTE *)sip->buf[sip->which])+sip->cnt,
sip->buflen-sip->cnt);
sip->req[sip->which].ioa_Request.io_Command=
sip->req[sip->which+2].ioa_Request.io_Command=CMD_WRITE;
sip->req[sip->which].ioa_Request.io_Flags=
sip->req[sip->which+2].ioa_Request.io_Flags=ADIOF_PERVOL;
sip->req[sip->which].ioa_Data=
sip->req[sip->which+2].ioa_Data=sip->buf[sip->which];
sip->req[sip->which].ioa_Length=
sip->req[sip->which+2].ioa_Length=sip->buflen;
sip->req[sip->which].ioa_Period=
sip->req[sip->which+2].ioa_Period=dmaclock/sip->samples;
sip->req[sip->which].ioa_Volume=
sip->req[sip->which+2].ioa_Volume=64;
sip->req[sip->which].ioa_Cycles=
sip->req[sip->which+2].ioa_Cycles=1;
if ((sip->channel==1)&&((sip->played[0]|sip->played[1])==0))
{
sip->req[4].ioa_Request.io_Command=CMD_STOP;
DoIO((struct IORequest *)&sip->req[4]);
}
BeginIO((struct IORequest *)&sip->req[sip->which]);
if (sip->channel==1)
{
BeginIO((struct IORequest *)&sip->req[sip->which+2]);
if ((sip->played[0]|sip->played[1])==0)
{
sip->req[4].ioa_Request.io_Command=CMD_START;
DoIO((struct IORequest *)&sip->req[4]);
}
}
sip->played[sip->which]=1;
cnt2+=sip->buflen-sip->cnt;
sip->which=1-sip->which;
sip->cnt=0;
if (sip->played[sip->which]==1)
{
WaitIO((struct IORequest *)&sip->req[sip->which]);
if (sip->channel==1)
WaitIO((struct IORequest *)&sip->req[sip->which+2]);
sip->played[sip->which]=0;
}
}
CopyMem(((UBYTE *)buf)+cnt2,
((UBYTE *)sip->buf[sip->which])+sip->cnt,
len-cnt2);
sip->cnt+=len-cnt2;
}
void parsepacket(dp)
struct DosPacket *dp;
{
struct streaminfo *sip;
LONG cnt2;
LONG min;
ULONG ident;
sip=(struct streaminfo *)dp->dp_Arg1;
cnt2=0;
while(dp->dp_Arg3>cnt2)
{
switch (sip->parserstate)
{
case no8svx:
playpacket(sip,((UBYTE *)dp->dp_Arg2)+cnt2,dp->dp_Arg3-cnt2);
cnt2=dp->dp_Arg3;
break;
case init:
min=MIN(12-sip->bufcnt,dp->dp_Arg3-cnt2);
CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
sip->parsebuf+sip->bufcnt,
min);
cnt2+=min;
sip->bufcnt+=min;
if (sip->bufcnt==12)
{
if((*(ULONG *)sip->parsebuf==0x464f524d)&&
(*(ULONG *)(sip->parsebuf+8)==0x38535658))
sip->parserstate=identifyhunk;
else
{
sip->parserstate=no8svx;
playpacket(sip,sip->parsebuf,12);
}
sip->bufcnt=0;
}
break;
default: /*identify,vhdr,body,readover*/
if ((sip->parserstate==identifyhunk)||(sip->chunkcnt==0))
{
min=MIN(4-sip->bufcnt,dp->dp_Arg3-cnt2);
CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
sip->parsebuf+sip->bufcnt,
min);
cnt2+=min;
sip->bufcnt+=min;
if (sip->bufcnt==4)
{
sip->bufcnt=0;
ident=*(ULONG *)sip->parsebuf;
if (sip->parserstate==identifyhunk)
{
switch (ident)
{
case 0x464f524d: /*FORM*/
sip->parserstate=init;
sip->bufcnt=4;
break;
case 0x56484452: /*VHDR*/
sip->parserstate=vhdr;
break;
case 0x424f4459: /*BODY*/
sip->parserstate=body;
break;
default:
sip->parserstate= readover;
break;
}
}
else
sip->chunkcnt=ident+ident%2;
}
}
else
{
min=MIN(sip->chunkcnt,dp->dp_Arg3-cnt2);
switch(sip->parserstate)
{
case vhdr:
CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
sip->parsebuf+sip->bufcnt,
min);
sip->bufcnt+=min;
if (sip->bufcnt==sizeof(struct VHDR))
{
if (sip->deflt==1)
sip->samples=((struct VHDR *)sip->parsebuf)->samplesPerSec;
sip->bufcnt=0;
}
break;
case body:
playpacket(sip,((UBYTE *)dp->dp_Arg2)+cnt2,min);
break;
}
sip->chunkcnt-=min;
cnt2+=min;
if (sip->chunkcnt==0)
sip->parserstate=identifyhunk;
}
break;
}
}
}
int openstream(dp)
struct DosPacket *dp;
{
struct streaminfo *sip;
struct MsgPort *mp;
struct FileHandle *fh;
static UBYTE channel0[]={2,4,1,8};
static UBYTE channel1[]={3,5,10,12};
static UBYTE *channels[4]= {channel0,channel1,channel0,channel0+2};
/* egal, stereo, left, right */
union {
ULONG channel;
APTR ptr;
} unit;
if ((sip=AllocMem(sizeof(struct streaminfo),MEMF_ANY|MEMF_CLEAR))!=NULL)
{
sip->buflen=buffers*BUFLEN;
if ((sip->buf[0]=AllocMem(sip->buflen,MEMF_CHIP))!=NULL)
{
if ((sip->buf[1]=AllocMem(sip->buflen,MEMF_CHIP))!=NULL)
{
if ((mp=CreatePort("",0))!=NULL)
{
parsename(sip,dp->dp_Arg3);
sip->req[0].ioa_Request.io_Message.mn_Node.ln_Type=NT_MESSAGE;
sip->req[0].ioa_Request.io_Message.mn_Length=sizeof(struct IOAudio);
sip->req[0].ioa_Request.io_Message.mn_ReplyPort=mp;
sip->req[0].ioa_Request.io_Command=ADCMD_ALLOCATE;
sip->req[0].ioa_Request.io_Flags=ADIOF_NOWAIT;
sip->req[0].ioa_Data=channels[sip->channel];
sip->req[0].ioa_Length=(sip->channel<2)?4:2;
sip->req[0].ioa_Request.io_Message.mn_Node.ln_Pri=75;
Forbid();
if (OpenDevice("audio.device",0,(struct IORequest *)&sip->req[0],0)==NULL)
{
sip->req[0].ioa_Request.io_Message.mn_Node.ln_Pri=127;
sip->req[0].ioa_Request.io_Command=ADCMD_SETPREC;
DoIO((struct IORequest *)&sip->req[0]);
Permit();
sip->req[4]=sip->req[1]=sip->req[0];
if (sip->channel==1)
{
sip->req[3]=sip->req[2]=sip->req[0];
unit.ptr=sip->req[4].ioa_Request.io_Unit;
unit.channel&=6;
sip->req[0].ioa_Request.io_Unit=
sip->req[1].ioa_Request.io_Unit=unit.ptr;
unit.ptr=sip->req[4].ioa_Request.io_Unit;
unit.channel&=9;
sip->req[2].ioa_Request.io_Unit=
sip->req[3].ioa_Request.io_Unit=unit.ptr;
}
sip->parserstate=init;
fh=(struct FileHandle *)BADDR(dp->dp_Arg1);
fh->fh_Arg1=(LONG)sip;
replypacket(dp,DOSTRUE,0);
return 1;
}
Permit();
DeletePort(mp);
}
FreeMem(sip->buf[1],sip->buflen);
}
FreeMem(sip->buf[0],sip->buflen);
}
FreeMem(sip,sizeof(struct streaminfo));
}
replypacket(dp,DOSFALSE,ERROR_NO_FREE_STORE);
return 0;
}
char *BSTR2C(bstr)
char *bstr;
{
static char cstr[256];
int i;
bstr=BADDR(bstr);
for(i=0;i<=bstr[0];i++)
cstr[i]=bstr[i+1];
cstr[i]=0;
return cstr;
}
void parsename(sip,bstr)
struct streaminfo *sip;
LONG bstr;
{
char *fn;
fn=BSTR2C((char *)bstr);
while(*(fn++)!=':');
*fn=tolower(*fn);
if ((*fn=='s')||(*fn=='l')||(*fn=='r'))
{
sip->channel=(*fn=='s')?1:(*fn=='l')?2:3;
fn++;
}
if ((sip->samples=atol(fn))==0)
{
sip->deflt=1;
sip->samples=SAMPLES;
}
}